#include "ScrGame.h"
#include "Renderer.h"
#include "ScreenManager.h"
#include "Game.h"
#include "base.h"
#include "Utils.h"

ScrGame::ScrGame(void) : GameScreen()
{
	m_pBlockRenderer = NULL;
	m_pWorld = NULL;
	m_pBlocks = NULL;
}
ScrGame::~ScrGame(void)
{
}
string ScrGame::GetInternalName()
{
	return string("main");
}
void ScrGame::Render()
{
	//Create camera projection
	m_pWorld->Draw();

	/*
	m_pBlockRenderer->BeginBlockDrawingAlt();
	m_pBlockRenderer->DrawBlockAlt(vector3(1,0,0), ScrGame::blockBedrock);
	m_pBlockRenderer->DrawBlockAlt(vector3(-1,0,0), ScrGame::blockBedrock);
	m_pBlockRenderer->DrawBlockAlt(vector3(0,1,0), ScrGame::blockBedrock);
	m_pBlockRenderer->DrawBlockAlt(vector3(0,-1,0), ScrGame::blockBedrock);
	m_pBlockRenderer->DrawBlockAlt(vector3(0,0,1), ScrGame::blockBedrock);
	m_pBlockRenderer->DrawBlockAlt(vector3(0,0,-1), ScrGame::blockBedrock);
	m_pBlockRenderer->EndBlockDrawingAlt();*/

	m_centralAxis.Draw(m_pRenderer);

	//Set projection back to ortho for rendering gui
	

	stringstream debugLine;
	vector3 camPos =  m_pCamera->GetPosition();
	debugLine << "Camera Pos {" 
		<< camPos.x << ", " <<camPos.y << ", " << camPos.z << "}\n";
	vector3 camRot =  m_pCamera->GetOrientation();
	debugLine << "Camera Rot {" 
		<< camRot.x << ", " <<camRot.y << ", " << camRot.z << "}\n";
	vector3 camDir = m_pCamera->GetDirection();
	debugLine << "Camera Direction {" 
		<< camDir.x << ", " <<camDir.y << ", " << camDir.z << "}\n";
	m_pRenderer->PrintStr2D(vector2(2, 16), debugLine.str(), color::White);
}
void ScrGame::Update()
{
	vector2 mouseState = GetMouse();
	vector2 mouseDelta = mouseState - m_lastMouse;

	vector3 originalRotation = m_pCamera->GetOrientation();
	originalRotation.x = clampf(originalRotation.x - mouseDelta.y * 1.0f, -80.0f , 80.0f);
	originalRotation.y -= mouseDelta.x * 1.0f;
	m_pCamera->SetOrientation(originalRotation);

	m_lastMouse = mouseState;

	int keyCount;
	byte *keys = SDL_GetKeyboardState(&keyCount);
	vector3 playerMod(0,0,0);
	float mod = 0.1f;
	if(keys[SDL_SCANCODE_LSHIFT] == 1)
	{
		mod = 1.5f;
	}
	if(keys[SDL_SCANCODE_W] == 1)
	{
		playerMod.z += mod;
	}
	if(keys[SDL_SCANCODE_S] == 1)
	{
		playerMod.z -= mod;
	}
	if(keys[SDL_SCANCODE_A] == 1)
	{
		playerMod.x += mod;
	}
	if(keys[SDL_SCANCODE_D] == 1)
	{
		playerMod.x -= mod;
	}
	if(keys[SDL_SCANCODE_SPACE] == 1)
	{
		playerMod.y += mod;
	}
	if(keys[SDL_SCANCODE_LCTRL] == 1)
	{
		playerMod.y -= mod;
	}

	m_pCamera->MoveFacing(playerMod);
	m_pWorld->Update();
}
bool ScrGame::ScreenInit(IGame *pGame)
{
	if(!GameScreen::ScreenInit(pGame))
		return false;

	//Create camera and assign it to the renderer
	m_pCamera = boost::shared_ptr<ICamera>((ICamera*)new Camera());

	CPrint(IBLUE, "Game started");
	CPrint(IBLUE, "Loading content..");
	m_pBlocks = new BlockLibrary();
	m_pBlockRenderer = new BlockRenderer();
	
	//Initialize block renderer
	m_pBlockRenderer->Initialize(m_pBlocks, m_pRenderer);

	//Set render camera
	m_pRenderer->SetActiveCamera(m_pCamera);
	m_pBlockRenderer->SetCamera(m_pCamera);

	//Load terrain texture
	m_nTextureTerrain = m_pBlockRenderer->GetTextureManager()->LoadTexture(FILE_DEFAULT_TERRAIN);
	if(!m_pBlockRenderer->GetTextureManager()->IsValidTexture(m_nTextureTerrain))
		return false;

	m_pBlockRenderer->SetTerrainTexture(m_nTextureTerrain);

	glErrorCheck();

	//Load blocks
	try {
		int btReg = RegisterBlockTemplates();
	} catch(...) {
		Error(cout << "failed to register block templates");
	}

	//Build block library
	m_pBlocks->BuildBlockLibrary();

	//Calculate block texture mappings
	m_pBlocks->PreCalculateBlockTextureMappings();

	CPrint(IBLUE, "Generating World");
	m_pWorld = new World();
	m_pWorld->Initialize(this, m_pBlocks, m_pBlockRenderer, m_nTextureTerrain);
	m_pWorld->Generate(123456);

	//Get player entity from world
	m_pPlayerEntity = m_pWorld->GetPlayerEntity();

	//Bind camera to player
	m_pPlayerEntity->LinkCamera(m_pCamera);

	//Get starting mouse position
	m_lastMouse = GetMouse();

	m_centralAxis.m_fAxisLength = 1.0f;
	m_centralAxis.m_position = vector3(0.0f, 0.0f, 0.0f);

	return true;
}
void ScrGame::OnScreenRemoved()
{
	CPrint(IBLUE, "Game cleanup started");
	Delete(m_pBlockRenderer);
	Delete(m_pBlocks);
	Delete(m_pWorld);
}
vector2 ScrGame::GetMouse()
{
	int x, y;
	SDL_GetMouseState(&x, &y);
	return vector2(x, y);
}
int ScrGame::RegisterCraftingRecipes()
{
	return CL_OK;
}
int ScrGame::RegisterItemTemplates()
{
	return CL_OK;
}
std::string ScrGame::GetInstanceName()
{
	return "core";
}
int ScrGame::GetLoaderType()
{
	return LT_CORE;
}